package com.lhy.mymall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lhy.mymall.common.Constant;
import com.lhy.mymall.exception.ExceptionEnum;
import com.lhy.mymall.exception.MallException;
import com.lhy.mymall.mapper.ProductMapper;
import com.lhy.mymall.pojo.Product;
import com.lhy.mymall.request.AddProductReq;
import com.lhy.mymall.request.ProductListReq;
import com.lhy.mymall.request.UpdateProductReq;
import com.lhy.mymall.service.ProductService;
import com.lhy.mymall.utils.ExcelUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.sound.sampled.Line;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author: 卢辉宇
 * @date: 2022/12/16 21:13
 * @description: 商品管理实现类
 */
@Service
public class ProductServiceImp implements ProductService {

    @Resource
    ProductMapper productMapper;

    @Override
    public Product selectByName(String name) {
        Product product = productMapper.selectByName(name);
        return product;
    }

    @Override
    public void addProduct(AddProductReq addProductReq) throws MallException {
        Product product = new Product();
        //通过spring的工具将传进来的对象复制给product
        BeanUtils.copyProperties(addProductReq, product);

        //重名检查，通过mapper层查询数据库。。。
        Product productOld = productMapper.selectByName(addProductReq.getName());
        if (productOld != null) {
            //数据库已存在同名商品
            throw new MallException(ExceptionEnum.NAME_EXISTED);
        }

        //向数据库插入商品
        int count = productMapper.insertProduct(product);
        if (count == 0) {
            //插入失败
            throw new MallException(ExceptionEnum.INSERT_FAILED);
        }
    }

    @Override
    public void updateProduct(UpdateProductReq updateProductReq) throws MallException {
        Product product = new Product();
        //把传进来的封装类复制成实体类
        BeanUtils.copyProperties(updateProductReq, product);

        //调用mapper层查找数据库是否存在相同的名字的商品
        Product productOld = productMapper.selectByName(product.getName());
        if (productOld != null && productOld.getId() != product.getId()) {
            //数据库有同名的，并且id不相同
            throw new MallException(ExceptionEnum.NAME_EXISTED);
        }

        //调用mapper层方法更新数据库。。。
        productMapper.updateById(product);
    }

    @Override
    public void deleteProduct(Integer id) throws MallException {
        int count = productMapper.deleteById(id);
        if (count == 0) {
            throw new MallException(ExceptionEnum.DELETE_FAILED);
        }
    }

    @Override
    public void batchUpdateShellStatus(Integer[] ids, Integer status) {
        //调用mapper层对数据库的批量操作。。。
        productMapper.batchUpdateShellStatus(ids, status);
    }

    @Override
    public PageInfo listForAdmin(Integer pageNum, Integer pageSize) {
        //调用分页
        PageHelper.startPage(pageNum, pageSize);

        //在mapper层把全部记录查询出来...
        List<Product> productList = productMapper.selectAll();

        //把查询到的记录用PageInfo封装起来
        PageInfo<Product> pageInfo = new PageInfo<>(productList);

        return pageInfo;
    }

    @Override
    public Product detail(Integer id) {
        //调用mapper层的查询。。。
        Product product = productMapper.selectById(id);
        return product;
    }

    @Override
    public PageInfo list(ProductListReq productListReq) {
        //关键字搜索处理
        /*判断用户名是否为空,空串和空格都算作空*/
        String keyWord = null;
        if (StringUtils.hasText(productListReq.getKeyWord())) {
            //用StringBuilder()来合成字符串，使之成为%keyWord%的格式
            keyWord = new StringBuilder().append("%").append(productListReq.getKeyWord()).append("%").toString();
        }

        //排序处理
        String orderBy = productListReq.getOrderBy();
        //注意不是orderBy传啥，就按照啥来排序的，要符合自定义的常量类中的定义规则进行排序。。。。
        if (Constant.PRICE_ASC_DESC.contains(orderBy)) {
            //orderBy的值，常量类中定义规则的规则包含有
            //用PageHelper工具进行分页排序
            PageHelper.startPage(productListReq.getPageNum(), productListReq.getPageSize(), orderBy);
        } else {
            //orderBy的值，常量类中定义规则的规则没有
            //用PageHelper工具进行分页,不排序
            PageHelper.startPage(productListReq.getPageNum(), productListReq.getPageSize());
        }

        //mapper层进行全部查找。。。
        List<Product> productList = productMapper.selectList(keyWord);

        //把全部记录封装层分页的记录
        PageInfo<Product> PageInfo = new PageInfo<>(productList);

        return PageInfo;
    }

    /**
     * 通过excel表格添加商品到数据库
     * @param destFile 传入的excel表格
     * @throws IOException
     * @throws MallException
     */
    @Override
    public void addProductByExcel(File destFile) throws IOException, MallException {
        //读取excel的信息...
        List<Product> products = readProductFromExcel(destFile);

        //遍历products并插入到数据库中
        for (int i = 0; i < products.size(); i++) {
            Product product = products.get(i);
            //先保证数据库中没有该名称的商品
            Product oldProduct = productMapper.selectByName(product.getName());
            if (oldProduct!=null){
                throw new MallException(ExceptionEnum.NAME_EXISTED);
            }
            //插入数据库
            int count = productMapper.insertProduct(product);
            if (count==0){
                throw new MallException(ExceptionEnum.INSERT_FAILED);
            }
        }

    }

    /**
     * 读取excel表格的逻辑处理，（把excel的行信息转化为product对象集合）
     * @param excelFile 含有product对应字段的excel表格
     * @return product列表对象
     * @throws IOException
     */
    private List<Product> readProductFromExcel(File excelFile) throws IOException {
        ArrayList<Product> listProducts = new ArrayList<>();
        //输入流读取文件
        FileInputStream inputStream = new FileInputStream(excelFile);

        /*利用xssf的方法读取excel表格并封装成对象*/
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        //获取表
        XSSFSheet firstSheet = workbook.getSheetAt(0);
        //得到行迭代器
        Iterator<Row> iterator = firstSheet.iterator();
        //遍历行
        while (iterator.hasNext()) {
            //得到一行
            Row nextRow = iterator.next();
            //得到这行的单元格迭代器
            Iterator<Cell> cellIterator = nextRow.cellIterator();
            //实例化一个商品，用来存放此行单元格的对象信息
            Product aProduct = new Product();
            //遍历列
            while (cellIterator.hasNext()) {
                //得到单元格
                Cell nextCell = cellIterator.next();
                //获取单元格的索引,并根据索引给对应的对象字段赋值
                int columnIndex = nextCell.getColumnIndex();
                switch (columnIndex) {
                    case 0:
                        aProduct.setName((String) ExcelUtil.getCellValue(nextCell));
                        break;
                    case 1:
                        aProduct.setImage((String) ExcelUtil.getCellValue(nextCell));
                        break;
                    case 2:
                        aProduct.setDetail((String) ExcelUtil.getCellValue(nextCell));
                        break;
                    case 3:
                        //数值类型的先强转成double再通过intValue()转化为整形
                        Double cellValue = (Double) ExcelUtil.getCellValue(nextCell);
                        aProduct.setCategoryId(cellValue.intValue());
                        break;
                    case 4:
                        cellValue = (Double) ExcelUtil.getCellValue(nextCell);
                        aProduct.setPrice(cellValue.intValue());
                        break;
                    case 5:
                        cellValue = (Double) ExcelUtil.getCellValue(nextCell);
                        aProduct.setStock(cellValue.intValue());
                        break;
                    case 6:
                        cellValue = (Double) ExcelUtil.getCellValue(nextCell);
                        aProduct.setStatus(cellValue.intValue());
                        break;
                }
            }
            //把赋值好了的对象放入list中
            listProducts.add(aProduct);
        }
        return listProducts;
    }

}
